package com.ouwen.smartpay.utils;

import com.alibaba.fastjson.JSONObject;
import com.fm.core.common.enums.TranStatus;
import com.fm.core.utils.Strings;
import com.fm.core.utils.enums.Messageable;
import com.fm.core.utils.enums.ResultStatus;
import com.google.common.collect.Maps;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="http://youngitman.tech">青年IT男</a>
 * @version v1.0.0
 * @className BeanUtil
 * @description
 * @JunitTest: {@link  }
 * @date 2020-04-23 11:54
 **/
public class BeanUtil {

    /**
     * 拷贝实体，source,target不允许为空
     *
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target) {
        BeanUtils.copyProperties(source, target);
    }

    /**
     * 拷贝实体集合，sourceList
     * 只支持自定义实体集合拷贝
     * 应用场景：DTO <=> DO 等
     */
    public static void copyPropertiesList(List sourceList, List targetList, Class clazz) throws InstantiationException, IllegalAccessException {
        if (CollectionUtils.isEmpty(sourceList)) {
            throw new IllegalArgumentException("集合不能为空");
        }
        for (Object items : sourceList) {
            Object target = clazz.newInstance();
            BeanUtils.copyProperties(items, target);
            targetList.add(target);
        }

    }

    /**
     * Map --> Bean 2: 利用org.apache.commons.beanutils 工具类实现 Map --> Bean
     *
     * @param map
     * @param obj
     */
    public static void transMap2Bean2(Map<String, Object> map, Object obj) throws InvocationTargetException, IllegalAccessException {
        if (map == null || obj == null) {
            return;
        }
        org.apache.commons.beanutils.BeanUtils.populate(obj, map);
    }

    /**
     * Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean
     *
     * @param map
     * @param obj
     */
    public static void transMap2Bean(Map<String, Object> map, Object obj) throws Exception {

        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());

        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

        for (PropertyDescriptor property : propertyDescriptors) {

            String key = property.getName();

            if (map.containsKey(key)) {

                if (!key.equals("class")) {

                    Object value = map.get(key);

                    // 得到property对应的setter方法
                    Method setter = property.getWriteMethod();

                    if (setter == null) {
                        continue;
                    }
                    //对结果转换特殊处理
                    if (Messageable.class.isAssignableFrom(property.getPropertyType()) && value != null) {

                        if ("tranStatus".equals(key)) {

                            setter.invoke(obj, TranStatus.findStatus(value.toString()));

                        } else if ("status".equals(key)) {

                            setter.invoke(obj, ResultStatus.findStatus(value.toString()));

                        }

                    } else if (property.getPropertyType() == Date.class) {

                        if (value != null && value instanceof Long) {

                            Date date = new Date((Long) value);

                            setter.invoke(obj, date);

                        }

                    } else {

                        Class<?> propertyType = property.getPropertyType();

                        if (propertyType instanceof Object &&
                                value != null && Map.class.isAssignableFrom(value.getClass())) {

                            if (Map.class.isAssignableFrom(propertyType)) {

                                setter.invoke(obj, value);

                            } else {

                                Object o = propertyType.newInstance();

                                transMap2Bean((HashMap) value, o);

                                setter.invoke(obj, o);

                            }


                        } else {

                            setter.invoke(obj, value);

                        }

                    }
                }
            }
        }
    }

    /**
     * Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
     *
     * @param obj
     */
    public static Map<String, Object> transBean2Map(Object obj) throws IntrospectionException, InvocationTargetException, IllegalAccessException {

        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();

            // 过滤class属性
            if (!key.equals("class")) {
                // 得到property对应的getter方法
                Method getter = property.getReadMethod();
                Object value = getter.invoke(obj);

                map.put(key, value);
            }

        }
        return map;
    }


    /***
     *@author <a href="http://youngitman.tech">青年IT男</a>
     *@version v1.0.0
     *@className BeanUtil
     *@description map转换json字符串
     *@JunitTest: {@link  }
     *@date 11:54 2020-04-26
     *
     **/
    public static String mapToJson(Map<String, Object> datas) {
        if (datas == null) {
            return new JSONObject().toJSONString();
        }
        JSONObject json = new JSONObject(datas);
        return json.toJSONString();
    }


    /***
     *
     * Json字符串转换Map
     *
     * @author liyong
     * @date 11:55 2020-04-26
     * @param json
     * @exception
     * @return java.util.Map<java.lang.String, java.lang.Object>
     **/
    public static Map<String, Object> jsonToMap(String json) {

        if (Strings.isEmpty(json)) {
            return Maps.newHashMap();
        }
        JSONObject jsonObject = JSONObject.parseObject(json);

        return jsonObject;
    }

}
